home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / x / gui / amiga / xfig.lha / src / x11 / w_canvas.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  12.1 KB  |  508 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  *
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. /*********************** IMPORTS ************************/
  14.  
  15. #include "fig.h"
  16. #include "figx.h"
  17. #include "resources.h"
  18. #include "mode.h"
  19. #include "paintop.h"
  20. #include <X11/keysym.h>
  21. #include "u_bound.h"
  22. #include "w_canvas.h"
  23. #include "w_mousefun.h"
  24. #include "w_setup.h"
  25. #include "w_util.h"
  26. #include "w_zoom.h"
  27. #ifndef SYSV
  28. #include "sys/time.h"
  29. #endif
  30. #include <X11/Xatom.h>
  31.  
  32. extern        erase_rulermark();
  33. extern        erase_objecthighlight();
  34. extern        char_handler();
  35.  
  36. /************** LOCAL STRUCTURE ***************/
  37.  
  38. typedef struct _CompKey CompKey;
  39.  
  40. struct _CompKey {
  41.     unsigned char   key;
  42.     unsigned char   first;
  43.     unsigned char   second;
  44.     CompKey       *next;
  45. };
  46.  
  47. /*********************** EXPORTS ************************/
  48.  
  49. int        (*canvas_kbd_proc) ();
  50. int        (*canvas_locmove_proc) ();
  51. int        (*canvas_leftbut_proc) ();
  52. int        (*canvas_middlebut_proc) ();
  53. int        (*canvas_middlebut_save) ();
  54. int        (*canvas_rightbut_proc) ();
  55. int        (*return_proc) ();
  56. int        null_proc();
  57. int        clip_xmin, clip_ymin, clip_xmax, clip_ymax;
  58. int        clip_width, clip_height;
  59. int        cur_x, cur_y;
  60.  
  61. String        local_translations = "";
  62.  
  63. /*********************** LOCAL ************************/
  64.  
  65. static CompKey *allCompKey = NULL;
  66. static        canvas_selected();
  67. static unsigned char getComposeKey();
  68. static        readComposeKey();
  69.  
  70. int        ignore_exp_cnt = 2;    /* we get 2 expose events at startup */
  71.  
  72. null_proc()
  73. {
  74.     /* almost does nothing */
  75.     if (highlighting)
  76.     erase_objecthighlight();
  77. }
  78.  
  79. static void
  80. canvas_exposed(tool, event, params, nparams)
  81.     TOOL        tool;
  82.     XButtonEvent   *event;
  83.     String       *params;
  84.     Cardinal       *nparams;
  85. {
  86.     static        xmin = 9999, xmax = -9999, ymin = 9999, ymax = -9999;
  87.     XExposeEvent   *xe = (XExposeEvent *) event;
  88.     register int    tmp;
  89.  
  90.     if (xe->x < xmin)
  91.     xmin = xe->x;
  92.     if (xe->y < ymin)
  93.     ymin = xe->y;
  94.     if ((tmp = xe->x + xe->width) > xmax)
  95.     xmax = tmp;
  96.     if ((tmp = xe->y + xe->height) > ymax)
  97.     ymax = tmp;
  98.     if (xe->count > 0)
  99.     return;
  100.  
  101.     /* kludge to stop getting extra redraws at start up */
  102.     if (ignore_exp_cnt)
  103.     ignore_exp_cnt--;
  104.     else
  105.     redisplay_region(xmin, ymin, xmax, ymax);
  106.     xmin = 9999, xmax = -9999, ymin = 9999, ymax = -9999;
  107. }
  108.  
  109. static void canvas_paste();
  110.  
  111. XtActionsRec    canvas_actions[] =
  112. {
  113.     {"EventCanv", (XtActionProc) canvas_selected},
  114.     {"ExposeCanv", (XtActionProc) canvas_exposed},
  115.     {"EnterCanv", (XtActionProc) draw_mousefun_canvas},
  116.     {"PasteCanv", (XtActionProc) canvas_paste},
  117.     {"LeaveCanv", (XtActionProc) clear_mousefun},
  118.     {"EraseRulerMark", (XtActionProc) erase_rulermark},
  119. };
  120.  
  121. /* need the ~Meta for the EventCanv action so that the accelerators still work */
  122. static String    canvas_translations =
  123. "<Motion>:EventCanv()\n\
  124.     Any<BtnDown>:EventCanv()\n\
  125.     <Key>F18: PasteCanv()\n\
  126.     <EnterWindow>:EnterCanv()\n\
  127.     <LeaveWindow>:LeaveCanv()EraseRulerMark()\n\
  128.     ~Meta<Key>:EventCanv()\n\
  129.     <Expose>:ExposeCanv()\n";
  130.  
  131. init_canvas(tool)
  132.     TOOL       tool;
  133. {
  134.     XColor       fixcolors[2];
  135.  
  136.     DeclareArgs(10);
  137.  
  138.     FirstArg(XtNlabel, "");
  139.     NextArg(XtNwidth, CANVAS_WD);
  140.     NextArg(XtNheight, CANVAS_HT);
  141.     NextArg(XtNfromHoriz, mode_panel);
  142.     NextArg(XtNhorizDistance, -INTERNAL_BW);
  143.     NextArg(XtNfromVert, topruler_sw);
  144.     NextArg(XtNvertDistance, -INTERNAL_BW);
  145.     NextArg(XtNtop, XtChainTop);
  146.     NextArg(XtNleft, XtChainLeft);
  147.     NextArg(XtNborderWidth, INTERNAL_BW);
  148.  
  149.     canvas_sw = XtCreateWidget("canvas", labelWidgetClass, tool,
  150.                    Args, ArgCount);
  151.  
  152.     FirstArg(XtNforeground, &x_fg_color.pixel);
  153.     NextArg(XtNbackground, &x_bg_color.pixel);
  154.     GetValues(canvas_sw);
  155.  
  156.     /*
  157.      * get the RGB values for recolor cursor use -- may want to have cursor
  158.      * color resource
  159.      */
  160.     fixcolors[0] = x_fg_color;
  161.     fixcolors[1] = x_bg_color;
  162.     XQueryColors(tool_d, DefaultColormapOfScreen(tool_s), fixcolors, 2);
  163.     x_fg_color = fixcolors[0];
  164.     x_bg_color = fixcolors[1];
  165.  
  166.     /* now fix the global GC */
  167.     XSetState(tool_d, gc, x_fg_color.pixel, x_bg_color.pixel, GXcopy,
  168.           AllPlanes);
  169.  
  170.     /* and recolor the cursors */
  171.     recolor_cursors();
  172.  
  173.     canvas_leftbut_proc = null_proc;
  174.     canvas_middlebut_proc = null_proc;
  175.     canvas_rightbut_proc = null_proc;
  176.     canvas_kbd_proc = canvas_locmove_proc = null_proc;
  177.     XtAppAddActions(tool_app, canvas_actions, XtNumber(canvas_actions));
  178.     XtAugmentTranslations(canvas_sw,
  179.                XtParseTranslationTable(canvas_translations));
  180.  
  181.     readComposeKey();
  182.  
  183.     return (1);
  184. }
  185.  
  186. setup_canvas()
  187. {
  188.     canvas_win = XtWindow(canvas_sw);
  189.     init_grid();
  190.     reset_clip_window();
  191. }
  192.  
  193. static
  194. canvas_selected(tool, event, params, nparams)
  195.     TOOL        tool;
  196.     XButtonEvent   *event;
  197.     String       *params;
  198.     Cardinal       *nparams;
  199. {
  200.     register int    x, y;
  201.     KeySym        key;
  202.     static int        sx = -10000, sy = -10000;
  203.     char        buf[1];
  204.     XButtonPressedEvent *be = (XButtonPressedEvent *) event;
  205.     XKeyPressedEvent *ke = (XKeyPressedEvent *) event;
  206.  
  207.     static char        compose_buf[2];
  208.     static char        compose_key = 0;
  209.     unsigned char   c;
  210.  
  211.     switch (event->type) {
  212.     case MotionNotify:
  213. #if defined(SMOOTHMOTION) || defined(OPENWIN)
  214.     /* translate from zoomed coords to object coords */
  215.     x = BACKX(event->x);
  216.     y = BACKY(event->y);
  217.  
  218.     /* perform appropriate rounding if necessary */
  219.     round_coords(x, y);
  220.  
  221.     if (x == sx && y == sy)
  222.         return;
  223.     sx = x;
  224.     sy = y;
  225. #else
  226.     {
  227.         Window        rw, cw;
  228.         int            rx, ry, cx, cy;
  229.         unsigned int    mask;
  230.  
  231.         XQueryPointer(event->display, event->window,
  232.               &rw, &cw,
  233.               &rx, &ry,
  234.               &cx, &cy,
  235.               &mask);
  236.         cx = BACKX(cx);
  237.         cy = BACKY(cy);
  238.  
  239.         /* perform appropriate rounding if necessary */
  240.         round_coords(cx, cy);
  241.  
  242.         if (cx == sx && cy == sy)
  243.         break;
  244.         x = sx = cx;    /* these are zoomed */
  245.         y = sy = cy;    /* coordinates!        */
  246.     }
  247. #endif /* SMOOTHMOTION || OPENWIN */
  248.     set_rulermark(x, y);
  249.     (*canvas_locmove_proc) (x, y);
  250.     break;
  251.     case ButtonPress:
  252.     /* translate from zoomed coords to object coords */
  253.     x = BACKX(event->x);
  254.     y = BACKY(event->y);
  255.  
  256.     /* Convert Alt-Button3 to Button2 */
  257.     if (be->button == Button3 && be->state & Mod1Mask) {
  258.         be->button = Button2;
  259.         be->state &= ~Mod1Mask;
  260.     }
  261.  
  262.     /* call interactive zoom function if control key is pressed */
  263.     if (be->state & ControlMask) {
  264.         zoom_selected(x, y, be->button);
  265.         break;
  266.     }
  267.     /* perform appropriate rounding if necessary */
  268.     round_coords(x, y);
  269.  
  270.     if (be->button == Button1)
  271.         (*canvas_leftbut_proc) (x, y, be->state & ShiftMask);
  272.     else if (be->button == Button2)
  273.         (*canvas_middlebut_proc) (x, y, be->state & ShiftMask);
  274.     else if (be->button == Button3)
  275.         (*canvas_rightbut_proc) (x, y, be->state & ShiftMask);
  276.     break;
  277.     case KeyPress:
  278.     /* we might want to check action_on */
  279.     /* if arrow keys are pressed, pan */
  280.     key = XLookupKeysym(ke, 0);
  281.     if (key == XK_Left ||
  282.         key == XK_Right ||
  283.         key == XK_Up ||
  284.         key == XK_Down ||
  285.         key == XK_Home ||
  286.         key == XK_Multi_key ||
  287.         key == XK_Alt_L ) {
  288.         switch (key) {
  289.         case XK_Left:
  290.         pan_left();
  291.         break;
  292.         case XK_Right:
  293.         pan_right();
  294.         break;
  295.         case XK_Up:
  296.         pan_up();
  297.         break;
  298.         case XK_Down:
  299.         pan_down();
  300.         break;
  301.         case XK_Home:
  302.         pan_origin();
  303.         break;
  304.         case XK_Multi_key:
  305.         case XK_Alt_L:
  306.         compose_key = 1;
  307.         break;
  308.         }
  309.     } else {
  310.         switch (compose_key) {
  311.         case 0:
  312.         if (XLookupString(ke, buf, sizeof(buf), NULL, NULL) > 0)
  313.             (*canvas_kbd_proc) ((unsigned char) buf[0]);
  314.         break;
  315.         case 1:
  316.         if (XLookupString(ke, &compose_buf[0], 1, NULL, NULL)
  317.             > 0)
  318.             compose_key = 2;
  319.         break;
  320.         case 2:
  321.         if (XLookupString(ke, &compose_buf[1], 1, NULL, NULL)
  322.             > 0) {
  323.             if ((c = getComposeKey(compose_buf)) != '\0')
  324.             (*canvas_kbd_proc) (c);
  325.             else {
  326.             (*canvas_kbd_proc) ((unsigned char) compose_buf[0]);
  327.             (*canvas_kbd_proc) ((unsigned char) compose_buf[1]);
  328.             }
  329.             compose_key = 0;
  330.         }
  331.         break;
  332.         }
  333.     }
  334.     break;
  335.     }
  336. }
  337.  
  338. clear_canvas()
  339. {
  340.     XClearArea(tool_d, canvas_win, clip_xmin, clip_ymin,
  341.            clip_width, clip_height, False);
  342. }
  343.  
  344. clear_region(xmin, ymin, xmax, ymax)
  345.     int            xmin, ymin, xmax, ymax;
  346. {
  347.     XClearArea(tool_d, canvas_win, xmin, ymin,
  348.            xmax - xmin + 1, ymax - ymin + 1, False);
  349. }
  350.  
  351. static void get_canvas_clipboard();
  352.  
  353. static void canvas_paste(w, paste_event)
  354. Widget w;
  355. XKeyEvent *paste_event;
  356. {
  357.     Time event_time;
  358.  
  359.     if (canvas_kbd_proc != char_handler)
  360.         return;
  361.  
  362.     if (paste_event != NULL)
  363.         event_time = paste_event->time;
  364.        else
  365.         time((time_t *) &event_time);
  366.     /***
  367.     This doesn't seem to work:
  368.     XtGetSelectionValue(w, XInternAtom(XtDisplay(w), "XA_PRIMARY", False),
  369.         XA_STRING, get_canvas_clipboard, NULL, event_time);
  370.     ***/
  371.     XtGetSelectionValue(w, XA_PRIMARY,
  372.         XA_STRING, get_canvas_clipboard, NULL, event_time);
  373. }
  374.  
  375. static void
  376. get_canvas_clipboard(w, client_data, selection, type, buf, length, format)
  377. Widget w;
  378. XtPointer client_data;
  379. Atom *selection;
  380. Atom *type;
  381. XtPointer buf;
  382. unsigned long *length;
  383. int *format;
  384. {
  385.     char *c;
  386.     int i;
  387.  
  388.     c = buf;
  389.     for (i=0; i<*length; i++) {
  390.            canvas_kbd_proc(*c);
  391.            c++;
  392.     }
  393.     XtFree(buf);
  394. }
  395.  
  396. static unsigned char
  397. getComposeKey(buf)
  398.     char       *buf;
  399. {
  400.     CompKey       *compKeyPtr = allCompKey;
  401.  
  402.     while (compKeyPtr != NULL) {
  403.     if (compKeyPtr->first == (unsigned char) (buf[0]) &&
  404.         compKeyPtr->second == (unsigned char) (buf[1]))
  405.         return (compKeyPtr->key);
  406.     else
  407.         compKeyPtr = compKeyPtr->next;
  408.     }
  409.     return ('\0');
  410. }
  411.  
  412. static
  413. readComposeKey()
  414. {
  415.     FILE       *st;
  416.     CompKey       *compKeyPtr;
  417.     char        line[255];
  418.     char       *p;
  419.     char       *p1;
  420.     char       *p2;
  421.     char       *p3;
  422.     long        size;
  423.     int            charfrom;
  424.     int            charinto;
  425.  
  426.  
  427. /* Treat the compose key DB a different way.  In this order:
  428.  *
  429.  *  1.    If the resource contains no "/", prefix it with the name of
  430.  *    the wired-in directory and use that.
  431.  *
  432.  *  2.    Otherwise see if it begins with "~/", and if so use that,
  433.  *    with the leading "~" replaced by the name of this user's
  434.  *    $HOME directory.
  435.  *
  436.  * This way a user can have private compose key settings even when running
  437.  * xfig privately.
  438.  *
  439.  * Pete Kaiser
  440.  * 24 April 1992
  441.  */
  442.  
  443.      /* no / in name, make relative to XFIGLIBDIR */
  444.      if (strchr(appres.keyFile, '/') == NULL) {
  445.      strcpy(line, XFIGLIBDIR);
  446.      strcat(line, "/");
  447.      strcat(line, appres.keyFile);
  448.      }
  449.  
  450.      /* expand the ~ to the user's home directory */
  451.      else if (! strncmp(appres.keyFile, "~/", 2)) {
  452.      strcpy(line, getenv("HOME"));
  453.      for (charinto = strlen(line), charfrom = 1;
  454.           line[charinto++] = appres.keyFile[charfrom++]; );
  455.        }
  456.     else
  457.     strcpy(line, appres.keyFile);
  458.  
  459.     if ((st = fopen(line, "r")) == NULL) {
  460.     allCompKey = NULL;
  461.     fprintf(stderr,"%cCan't open compose key file '%s',\n",007,line);
  462.     fprintf(stderr,"\tno multi-key sequences available\n");
  463.     return;
  464.     }
  465.     fseek(st, 0, 2);
  466.     size = ftell(st);
  467.     fseek(st, 0, 0);
  468.  
  469.     local_translations = (String) malloc(size + 1);
  470.  
  471.     strcpy(local_translations, "");
  472.     while (fgets(line, 250, st) != NULL) {
  473.     if (line[0] != '#') {
  474.         strcat(local_translations, line);
  475.         if ((p = strstr(line, "Multi_key")) != NULL) {
  476.         if (allCompKey == NULL) {
  477.             allCompKey = (CompKey *) malloc(sizeof(CompKey));
  478.             compKeyPtr = allCompKey;
  479.         } else {
  480.             compKeyPtr->next = (CompKey *) malloc(sizeof(CompKey));
  481.             compKeyPtr = compKeyPtr->next;
  482.         }
  483.  
  484.         p1 = strstr(p, "<Key>") + strlen("<Key>");
  485.         p = strstr(p1, ",");
  486.         *p++ = '\0';
  487.         p2 = strstr(p, "<Key>") + strlen("<Key>");
  488.         p = strstr(p2, ":");
  489.         *p++ = '\0';
  490.         p3 = strstr(p, "insert-string(") + strlen("insert-string(");
  491.         p = strstr(p3, ")");
  492.         *p++ = '\0';
  493.  
  494.         if (strlen(p3) == 1)
  495.             compKeyPtr->key = *p3;
  496.         else
  497.             compKeyPtr->key = strtol(p3, NULL, 16);
  498.         compKeyPtr->first = XStringToKeysym(p1);
  499.         compKeyPtr->second = XStringToKeysym(p2);
  500.         compKeyPtr->next = NULL;
  501.         }
  502.     }
  503.     }
  504.  
  505.     fclose(st);
  506.  
  507. }
  508.